<template>
  <div class="HotTechnical">
    <div id="container">
      <div style="overflow: hidden;"></div>
    </div>
    <div class = "sort">
      <el-form :inline="true" class="demo-form-inline">
        <el-form-item label="">
          <el-select v-model="gradeId" placeholder="请选择系" @change="getMajor">
            <el-option v-for="item in gradeList" :key="item.labelId" :label="item.label" :value="item.labelId"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="">
          <el-select v-model="majorId" placeholder="请选择专业" @change="getHotWord">
            <el-option v-for="item in majorList" :key="item.labelId" :label="item.label" :value="item.labelId"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
    </div>
    <div id="menu">
      <button id="table">表格</button>
      <button id="sphere">球体</button>
      <button id="helix">螺旋</button>
      <button id="grid">网格</button>
    </div>
  </div>
</template>

<script>
import * as THREE from "../../assets/common/three.js";
import renderer from "../../assets/common/CSS3DRenderer.js";
import trackball from "../../assets/common/TrackballControls.js";
import { _getHotWords } from '../../network/dissertation.js'
import { _getGrade, _getMajor } from '../../network/common.js'

var timer = 1;
var timeInterval = '';
export default {
  name: "HotTechnical",
  data() {
    return {
      positionArr: [
        // 缩写、全称、放射率、position位置
        1,
        1,
        1,
        2,
        2,
        1,
        2,
        2,
        1,
        3,
        2,
        3,
        1,
        4,
        2,
        4,
        3,
        4,
        4,
        4,
        5,
        4,
        6,
        4,
        7,
        4,
        8,
        1,
        8,
        2,
        8,
        3,
        8,
        4,
        9,
        1,
        9,
        2,
        9,
        3,
        9,
        4,
        1,
        5,
        2,
        5,
        3,
        5,
        3,
        6,
        3,
        7,
        3,
        8,
        3,
        9,
        4,
        5,
        5,
        5,
        6,
        5,
        7,
        5,
        8,
        5,
        9,
        5,
        1,
        6,
        2,
        6,
        4,
        8,
        5,
        8,
        6,
        8,
        7,
        8,
        8,
        8,
        9,
        8,
        9,
        10,
        9,
        11,
        9,
        12,
        4,
        6,
        5,
        6,
        6,
        6,
        7,
        6,
        8,
        6,
        9,
        6,
        1,
        7,
        1,
        8,
        1,
        9,
        1,
        10,
        1,
        11,
        1,
        12,
        2,
        7,
        2,
        8,
        2,
        9,
        2,
        10,
        2,
        11,
        2,
        12,
        4,
        9,
        5,
        9,
        6,
        9,
        7,
        9,
        8,
        9,
        8,
        10,
        8,
        11,
        8,
        12,
        9,
        9,
        4,
        7,
        5,
        7,
        6,
        7,
        7,
        7,
        8,
        7,
        9,
        7,
      ],
      gradeList: [],
      majorList: [],
      hotwordList: [],
      gradeId: '',
      majorId: ''
      // timeInterval: '' 
      // timer: 1
    };
  },
  mounted() {
    /* 获取系类别信息 */
    _getGrade().then(res => {
      if(res.data.code === 200){
        this.gradeList = res.data.gradeList
        this.gradeId = this.gradeList[0].labelId
        this.getMajor()
        this.majorId = 11
        this.getHotWord()
      } else {
        switch(res.headers.flag){
          case '-1':
            this.$message.error('请先登录')
            this.$router.push('/login')
            break
          case '-2':
            localStorage.removeItem('token')
            this.$message.error('token错误或已失效，请重新登录')
            this.$router.push('/login')
            break
          default:
            this.$message.error('系别获取数据失败')
            break;
        }
      }
    }).catch(res => {
      this.$message.error("未知错误，请联系管理员")
    })
  },
  methods: {
    getHotWord () {
      clearInterval(timeInterval)
      timer = 1
      let majorId = parseInt(this.majorId)
      _getHotWords(majorId).then(res => {
        if(res.data.code == 200){
          this.hotwordList = res.data.keywordList
          this.initMap()
        } else {
          this.$message.error('热门词汇数据获取失败')
        }
      }).catch(res => {
        this.$message.error('未知错误，请联系管理员')
      })
    },
    /* 获取专业 */
    getMajor () {
      let gradeId = parseInt(this.gradeId)
      _getMajor(gradeId).then(res => {
        if(res.data.code === 200){
          this.majorList = res.data.majorList
        } else {
          this.$message.error("获取专业数据失败")
        }
      }).catch(res => {
        this.$message.error("未知错误，请联系管理员")
      })
    },
    initMap() {

      // 相机、场景、渲染器
      var camera, scene, renderer;
      // 控制器
      var controls;

      var objects = [];
      // 四种表示形式
      var targets = { table: [], sphere: [], helix: [], grid: [] };

      init(this.hotwordList,this.positionArr);
      animate();

      var targetList = [targets.table,targets.sphere,targets.helix,targets.grid]
      
      /* 定时器 */
      function runInterval(){
        timeInterval = setInterval(() => {
          transform(targetList[timer], 1800);
          if(timer == 3){
            timer = 0;
          } else {
            timer++;
          }
        },5000)
      }

      runInterval();

      function init(hotwordList,positionArr) {
        // 透视摄像机（透视投影照相机对应投影到的物体的大小是随着距离逐渐变小的，
        // 而正投影照相机投影到的物体大小是不受距离影响的）
        document.getElementById('container').innerHTML = ''
        let width = document.getElementById('container').clientWidth
        let height = document.getElementById('container').clientWidth
        camera = new THREE.PerspectiveCamera(
          40,
          width / height,
          1,
          10000
        );
        // z轴距离最远距离（即物体离人眼的距离）
        camera.position.z = 3000;
        scene = new THREE.Scene();

        // table


        for (var i = 0; i < hotwordList.length; i++) {
          // 创建卡片的框架
          var element = document.createElement("div");
          element.className = "element";
          element.style.backgroundColor =
            "rgba(0,127,127," + (Math.random() * 0.5 + 0.25) + ")";

          /* 卡片名 */
          var symbol = document.createElement("div");
          symbol.className = "symbol";
          symbol.textContent = hotwordList[i];
          element.appendChild(symbol);

          /* 向场景中添加3D物体对象 */
          var object = new THREE.CSS3DObject(element);
          object.position.x = Math.random() * 4000 - 1800;
          object.position.y = Math.random() * 4000 - 1800;
          object.position.z = Math.random() * 4000 - 1800;
          scene.add(object);

          objects.push(object);

          // 卡片的位置（这里因为没有透视效果，所以不用设置z轴）
          var object = new THREE.Object3D();
          // i = 0     0     1
          // i = 1     2     3
          // i = 2     4     5
          // i = 3     6     7
          // i = 4     8     9
          object.position.x = positionArr[2 * i] * 250 - 1200;
          object.position.y = -(positionArr[2 * i + 1] * 150) + 990;
          targets.table.push(object);
        }

        // sphere
        // 向量
        var vector = new THREE.Vector3();

        for (var i = 0, l = objects.length; i < l; i++) {
          // acos 方法以 -1 到 1 的一个数为参数，返回一个 0 到 pi （弧度）的数值
          var phi = Math.acos(-1 + (2 * i) / l);
          // 开平方，返回0到pi*3的数值
          var theta = Math.sqrt(l * Math.PI) * phi;
          var object = new THREE.Object3D();

          object.position.setFromSphericalCoords(800, phi, theta);
          // radius,phi,theta

          vector.copy(object.position).multiplyScalar(2);

          object.lookAt(vector);

          targets.sphere.push(object);
        }

        // helix

        var vector = new THREE.Vector3();

        for (var i = 0, l = objects.length; i < l; i++) {
          var theta = i * 0.2 + Math.PI;
          var y = -(i * 8) + 450;

          var object = new THREE.Object3D();

          object.position.setFromCylindricalCoords(900, theta, y);

          vector.x = object.position.x * 2;
          vector.y = object.position.y;
          vector.z = object.position.z * 2;

          object.lookAt(vector);

          targets.helix.push(object);
        }

        // grid

        for (var i = 0; i < objects.length; i++) {
          var object = new THREE.Object3D();

          object.position.x = (i % 5) * 400 - 800;
          object.position.y = -(Math.floor(i / 5) % 5) * 400 + 800;
          object.position.z = Math.floor(i / 25) * 1000 - 1800;

          targets.grid.push(object);
        }

        //  3D渲染器

        renderer = new THREE.CSS3DRenderer();
        renderer.setSize(width, window.innerHeight - 100);
        document.getElementById("container").appendChild(renderer.domElement);

        // 控制器
        controls = new THREE.TrackballControls(camera, renderer.domElement);
        controls.minDistance = 500;
        controls.maxDistance = 6000;
        controls.addEventListener("change", render);

        // table
        var button = document.getElementById("table");
        button.addEventListener(
          "click",
          () => {
            clearInterval(timeInterval)
            timer = 1
            transform(targets.table, 1800);
            runInterval();
          },
          false
        );

        // sphere
        var button = document.getElementById("sphere");
        button.addEventListener(
          "click",
          () => {
            clearInterval(timeInterval)
            transform(targets.sphere, 1800);
            timer = 2
            runInterval();
          },
          false
        );

        // helix
        var button = document.getElementById("helix");
        button.addEventListener(
          "click",
          () => {
            clearInterval(timeInterval)
            transform(targets.helix, 1800);
            timer = 3
            runInterval();
          },
          false
        );

        // grid
        var button = document.getElementById("grid");
        button.addEventListener(
          
          "click",
          () => {
            clearInterval(timeInterval)
            transform(targets.grid, 1800);
            timer = 0
            runInterval();
          },
          false
        );

        // 默认渲染table形式
        transform(targets.table, 1800);
        window.addEventListener("resize", onWindowResize, false);
      }

      function transform(targets, duration) {
        // 先移除之前的效果
        TWEEN.removeAll();

        for (var i = 0; i < objects.length; i++) {
          var object = objects[i];

          var target = targets[i];

          // tween.js允许以平滑的方式修改元素的属性值
          // 平滑移动
          new TWEEN.Tween(object.position)
            .to(
              {
                x: target.position.x,
                y: target.position.y,
                z: target.position.z,
              },
              Math.random() * duration + duration
            )
            .easing(TWEEN.Easing.Exponential.InOut)
            .start();

          // 平滑转变角度
          new TWEEN.Tween(object.rotation)
            .to(
              {
                x: target.rotation.x,
                y: target.rotation.y,
                z: target.rotation.z,
              },
              Math.random() * duration + duration
            )
            .easing(TWEEN.Easing.Exponential.InOut)
            .start();
        }

        new TWEEN.Tween(this)
          .to({}, duration * 2)
          .onUpdate(render)
          .start();
      }


      /* 窗口尺寸自适应 */
      function onWindowResize() {
        let width = document.getElementById('container').clientWidth
        let height = document.getElementById('container').clientWidth
        camera.aspect = width / height;
        camera.updateProjectionMatrix();
        renderer.setSize(width, window.innerHeight - 100)
        render();
      }
      /* 添加动画效果 */
      function animate() {
        requestAnimationFrame(animate);
        TWEEN.update();

        controls.update();
      }

      /* 渲染 */
      function render() {
        renderer.render(scene, camera);
      }
    },
  },
};
</script>

<style>

.HotTechnical {
    height: 100%;
    margin: 0;
    background-color: #000;
    color: #fff;
    font-family: Monospace;
    font-size: 13px;
    line-height: 24px;
}

a {
    color: #ff0;
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

button {
    cursor: pointer;
    text-transform: uppercase;
}

canvas {
    display: block;
}

#info {
    position: absolute;
    top: 0px;
    width: 100%;
    padding: 10px;
    box-sizing: border-box;
    text-align: center;
    z-index: 1; /* TODO Solve this in HTML */
}

.dg.ac {
    z-index: 2 !important; /* TODO Solve this in HTML */
}
a {
  color: #8ff;
}
#container {
  width: 100%;
  height: 100%;
  margin: 0 auto;
  overflow: hidden;
}
.sort{
  position: absolute;
  top: 18px;
  width: 100%;
  text-align: center;
}
#menu {
  position: absolute;
  bottom: 18px;
  width: 100%;
  text-align: center;
}

.element {
  width: 200px;
  height: 70px;
  box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.5);
  border: 1px solid rgba(127, 255, 255, 0.25);
  font-family: Helvetica, sans-serif;
  text-align: center;
  line-height: 70px;
  cursor: default;
}

.element:hover {
  box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.75);
  border: 1px solid rgba(127, 255, 255, 0.75);
}

.element .number {
  position: absolute;
  top: 18px;
  right: 18px;
  font-size: 12px;
  color: rgba(127, 255, 255, 0.75);
}

.element .symbol {
  position: absolute;
  top: 0px;
  left: 0px;
  right: 0px;
  font-size: 30px;
  font-weight: bold;
  color: rgba(255, 255, 255, 0.75);
  text-shadow: 0 0 10px rgba(0, 255, 255, 0.95);
}

.element .details {
  position: absolute;
  bottom: 15px;
  left: 0px;
  right: 0px;
  font-size: 12px;
  color: rgba(127, 255, 255, 0.75);
}

button {
  color: rgba(127, 255, 255, 0.75);
  background: transparent;
  outline: 1px solid rgba(127, 255, 255, 0.75);
  border: 0px;
  padding: 5px 10px;
  cursor: pointer;
}

button:hover {
  background-color: rgba(0, 255, 255, 0.5);
}

button:active {
  color: #000000;
  background-color: rgba(0, 255, 255, 0.75);
}
</style>
